package geppetto.cat.alignments;

import geppetto.cat.alignments.output.AlignerOutput;
import geppetto.cat.common.Pair;
import geppetto.cat.common.StaticTools;
import geppetto.cat.corpus.BilingualCorpus;
import gnu.trove.TIntArrayList;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.regex.Pattern;



/**
 * Alignment - Represents a word alignment. Consists of a matrix of sourceSize *
 * foreingSize where each entry indicates if a word in one language is part of a
 * translation of another.
 * 
 * @author javg
 * 
 */
public class Alignment {

	static int UNALIGNED_POINT = 0;
	static int POSSIBLE_POINT = 1;
	static int SURE_POINT = 2;

	// 0 - no Align 1 - Possible 2 - Sure
	// Just for visualization effects:
	// 3 Intersect , 4 Union , 5 Grow, 6 Grow Final

	public byte[][] _alignment; 

	public double[][] _posteriors;

	// Used to desambiguate the sentence number
	public byte _sentenceSource; // 0 - train 1 - test 2 - dev

	public int _sentenceNumber; // Number of the sentence in a given source

	public int _sourceLen;

	public int _foreignLen;

	// TODO Should return real score
	public double _score = 0;

	public static ArrayList<Pair<Integer, Integer>> MASK = createMask();

	public static ArrayList<Pair<Integer, Integer>> createMask() {
		ArrayList<Pair<Integer, Integer>> mask = new ArrayList<Pair<Integer, Integer>>();
		mask.add(new Pair<Integer, Integer>(-1, -1));
		mask.add(new Pair<Integer, Integer>(-1, 0));
		mask.add(new Pair<Integer, Integer>(0, -1));
		mask.add(new Pair<Integer, Integer>(0, 1));
		mask.add(new Pair<Integer, Integer>(1, 0));
		mask.add(new Pair<Integer, Integer>(1, 1));
		mask.add(new Pair<Integer, Integer>(-1, 1));
		mask.add(new Pair<Integer, Integer>(1, -1));
		return mask;
	}

	public Alignment(int sentenceNumber, byte sentenceSource, int sourceLen,
			int foreignLen) {
		// System.out.println(sourceLen + " " + foreignLen);
		_sentenceNumber = sentenceNumber;
		_sourceLen = sourceLen;
		_foreignLen = foreignLen;
		_sentenceSource = sentenceSource;
		_alignment = new byte[_sourceLen][_foreignLen];
		_posteriors = new double[_sourceLen][_foreignLen];
		for (int i = 0; i < _sourceLen; i++)
			for (int j = 0; j < _foreignLen; j++)
				_alignment[i][j] = 0;
	}

	public void addPosterior(int sourcePos, int foreignPos, double value) {
		_posteriors[sourcePos][foreignPos] = value;
	}

	public boolean equals(Alignment al) {

		if (_sentenceNumber != al._sentenceNumber
				|| _sourceLen != al._sourceLen || _foreignLen != al._foreignLen)
			return false;
		for (int i = 0; i < _sourceLen; i++)
			for (int j = 0; j < _foreignLen; j++)
				if (_alignment[i][j] != al._alignment[i][j])
					return false;
		return true;
	}

	public Alignment(Alignment copy) {
		_sentenceNumber = copy._sentenceNumber;
		_sourceLen = copy._sourceLen;
		_foreignLen = copy._foreignLen;
		_sentenceSource = copy._sentenceSource;
		_alignment = new byte[_sourceLen][_foreignLen];
		_posteriors = new double[_sourceLen][_foreignLen];
		for (int i = 0; i < _sourceLen; i++)
			for (int j = 0; j < _foreignLen; j++){
				_alignment[i][j] = copy._alignment[i][j];
				_posteriors[i][j] = copy._posteriors[i][j];
			}


	}

	public Alignment reverse() {
		Alignment rev = new Alignment(_sentenceNumber, _sentenceSource,
				_foreignLen, _sourceLen);
		byte[][] alR = new byte[getForeignLenght()][getSourceLenght()];
		double[][] posR = new double[getForeignLenght()][getSourceLenght()];
		for (int i = 0; i < getSourceLenght(); i++) {
			for (int j = 0; j < getForeignLenght(); j++) {
				alR[j][i] = _alignment[i][j];
				posR[j][i] = _posteriors[i][j];
			}
		}
		rev._alignment = alR;
		rev._posteriors = posR;
		return rev;
	}

	/**
	 * Removes all alignment points
	 * Leaves the posteriors
	 *
	 */
	public void resetPoints(){
		for (int i = 0; i < getSourceLenght(); i++) {
			for (int j = 0; j < getForeignLenght(); j++){
				_alignment[i][j] = 0;
			}
		}

	}

	public void resetPosteriors(){
		for (int i = 0; i < getSourceLenght(); i++) {
			for (int j = 0; j < getForeignLenght(); j++){
				_posteriors[i][j] = 0;
			}
		}

	}

	public int getSentenceNumber() {
		return _sentenceNumber;
	}

	public byte getSentenceSource() {
		return _sentenceSource;
	}

	public boolean sourceWordIsAligned(int sourceIndex) {
		if (sourceIndex >= getSourceLenght() || sourceIndex < 0)
			return false;
		for (int i = 0; i < getForeignLenght(); i++) {
			if (hasPosition(sourceIndex, i))
				return true;
		}
		return false;
	}

	public boolean foreignWordIsAligned(int foreignIndex) {
		if (foreignIndex >= getForeignLenght() || foreignIndex < 0)
			return false;
		for (int i = 0; i < getSourceLenght(); i++) {
			if (hasPosition(i, foreignIndex))
				return true;
		}
		return false;
	}

	public boolean hasPosition(int sourceIndex, int foreignIndex) {
		if (foreignIndex >= getForeignLenght() || foreignIndex < 0)
			return false;
		if (sourceIndex >= getSourceLenght() || sourceIndex < 0)
			return false;
		return _alignment[sourceIndex][foreignIndex] != 0;
	}

	public boolean isPossible(int sourceIndex, int foreignIndex) {
		return _alignment[sourceIndex][foreignIndex] == 1;
	}

	public boolean isSure(int sourceIndex, int foreignIndex) {
		return _alignment[sourceIndex][foreignIndex] >= 2; // All alignments
		// produced are sure
		// in our case
	}

	public int getSourceLenght() {
		return _sourceLen;
	}

	public int getForeignLenght() {
		return _foreignLen;
	}

	public void add(int sindex, int findex, byte type) {
		_alignment[sindex][findex] = type;
	}

	public void add(int sindex, int findex) {
		_alignment[sindex][findex] = 2;
	}

	public void addNullCollum(int findex) {
		for (int i = 0; i < _sourceLen; i++)
			_alignment[i][findex] = 0;
	}

	public TIntArrayList getSurePosition(int foreignPosition) {
		TIntArrayList surePositions = new TIntArrayList();
		for (int i = 0; i < getSourceLenght(); i++) {
			if (_alignment[i][foreignPosition] == 2)
				surePositions.add(i);
		}
		return surePositions;
	}

	public TIntArrayList getPossiblePosition(int foreignPosition) {
		TIntArrayList possiblePositions = new TIntArrayList();
		for (int i = 0; i < getSourceLenght(); i++) {
			if (_alignment[i][foreignPosition] == 1)
				possiblePositions.add(i);
		}
		return possiblePositions;
	}

	/**
	 * Defines different print symbols according to the type of alignmet
	 *  0  - no type (the normal produced by an algorithm
	 *  1 - Possible point
	 *  2 - Sure point
	 *  //The rest of the values are used for pretty printing mostly
	 *  // And say which symetrization heuristic produced the point
	 *  3 -  Intersection
	 *  4 - Union
	 *  5 - Grow Diag 
	 *  6 - Grow Diag and Final 
	 * @param source
	 * @param foreign
	 * @return
	 */
	public String getPrintSymbol(int source, int foreign) {
		int i = _alignment[source][foreign];
		switch (i) {
		case 0:
			return "   ";
		case 1:
			return " P ";
		case 2:
			return " S ";
		case 3:
			return " I ";
		case 4:
			return " U ";
		case 5:
			return " G ";
		case 6:
			return " F ";
		default:
			return "   ";
		}
	}

	/** Statistics Function */
	public int getNumberNulls() {
		int nrNull = 0;
		for (int foreignPos = 0; foreignPos < getForeignLenght(); foreignPos++) {
			boolean isNull = true;
			for (int sourcePos = 0; sourcePos < getSourceLenght(); sourcePos++) {
				if (_alignment[sourcePos][foreignPos] != 0)
					isNull = false;
			}
			if (isNull)
				nrNull++;
		}
		return nrNull;
	}

	public int getNumberOfForeignNotAligned() {
		int nrNull = 0;
		for (int foreignPos = 0; foreignPos < getForeignLenght(); foreignPos++) {
			boolean isNull = true;
			for (int sourcePos = 0; sourcePos < getSourceLenght(); sourcePos++) {
				if (_alignment[sourcePos][foreignPos] != 0)
					isNull = false;
			}
			if (isNull)
				nrNull++;
		}
		return nrNull;
	}

	public int getNumberOfSourceNotAligned() {
		int nrNull = 0;
		for (int sourcePos = 0; sourcePos < getSourceLenght(); sourcePos++) {
			boolean isNull = true;
			for (int foreignPos = 0; foreignPos < getForeignLenght(); foreignPos++) {
				if (_alignment[sourcePos][foreignPos] != 0)
					isNull = false;
			}
			if (isNull)
				nrNull++;
		}
		return nrNull;
	}

	public int numberOfAlignedPoints() {
		int i = 0;
		for (int j = 0; j < _sourceLen; j++) {
			for (int k = 0; k < _foreignLen; k++) {
				if (hasPosition(j, k))
					i++;
			}
		}
		return i;
	}

	public int numberOfAlignedPoints(int type) {
		int i = 0;
		for (int j = 0; j < _sourceLen; j++) {
			for (int k = 0; k < _foreignLen; k++) {
				if (_alignment[j][k] == type)
					i++;
			}
		}
		return i;
	}

	public double meanFertility() {
		int[] fet = fertilityPerWord();
		double mean = 0f;
		for (int i = 0; i < _sourceLen; i++) {
			mean += fet[i];
		}
		return mean * 1.0 / _sourceLen;
	}

	/**
	 * Calculate the fertility of each source word in the sentence
	 * 
	 */
	public int[] fertilityPerWord() {
		int[] fet = new int[_sourceLen];
		for (int i = 0; i < _sourceLen; i++) {
			int k = 0;
			for (int j = 0; j < _foreignLen; j++) {
				if (hasPosition(i, j))
					k++;
			}
			// System.out.print(k);
			fet[i] = k;
		}
		return fet;
	}

	// TODO should receive mask to look for instead of fixed points
	public boolean hasNeighbour(int sPos, int fPos, int sLenght, int fLenght,
			ArrayList<Pair<Integer, Integer>> mask) {
		for (Pair p : mask) {
			int nsPos = (Integer) p.first() + sPos;
			int nfPos = (Integer) p.second() + fPos;
			if (nsPos >= 0 && nsPos < sLenght && nfPos >= 0 && nfPos < fLenght)
				if (hasPosition(nsPos, nfPos))
					return true;
		}
		return false;
	}

	public int numberOfLonelyPoints(ArrayList<Pair<Integer, Integer>> mask) {
		int points = 0;
		for (int j = 0; j < _sourceLen; j++) {
			for (int k = 0; k < _foreignLen; k++) {
				if (hasPosition(j, k)
						&& !hasNeighbour(j, k, _sourceLen, _foreignLen, mask))
					points++;
			}
		}
		return points;
	}

	// Return the lonely points
	// 0 - Lonely points correct
	// 1 - Lonely points incorrect

	public int[] getLonelyPoints(Alignment gold,
			ArrayList<Pair<Integer, Integer>> mask) {
		int[] points = new int[2];
		for (int j = 0; j < _sourceLen; j++) {
			for (int k = 0; k < _foreignLen; k++) {
				if (hasPosition(j, k)
						&& !hasNeighbour(j, k, _sourceLen, _foreignLen, mask))
					if (gold.hasPosition(j, k))
						points[0]++;
					else
						points[1]++;
			}
		}
		return points;
	}

	// Average number of points that are outside the main diagonal
	public double distanceToDiagonal() {
		double variance = 0;
		int nPoints = 0;
		for (int j = 0; j < _sourceLen; j++) {
			for (int k = 0; k < _foreignLen; k++) {
				if (hasPosition(j, k))
					variance += Math.abs(j - k);
				nPoints++;
			}
		}
		return variance / nPoints;
	}

	public String toString() {
		String al = "";
		al += "\t";
		for (int foreignPos = 0; foreignPos < getForeignLenght(); foreignPos++) {
			al += foreignPos + "\t";
		}
		al += "\n";
		for (int sourcePos = 0; sourcePos < getSourceLenght(); sourcePos++) {
			al += sourcePos + "\t";
			for (int foreignPos = 0; foreignPos < getForeignLenght(); foreignPos++) {
				al += hasPosition(sourcePos, foreignPos) + "\t";
			}
			al += "\n";
		}

		return al;
	}

	public boolean emptyColumn(int foreignPosition) {
		for (int i = 0; i < getSourceLenght(); i++) {
			if (hasPosition(i, foreignPosition))
				return false;
		}
		return true;
	}

	public boolean emptyRow(int sourcePosition) {
		for (int i = 0; i < getForeignLenght(); i++) {
			if (hasPosition(i, sourcePosition))
				return false;
		}
		return true;
	}






	/**Input/Output Functions */

	// All indexes begin at 1
	// Non aligned words don't appear
	public String toHazardFormat() {
		String reply = "";
		int aux = 10001 + _sentenceNumber;
		String sn = "" + aux;
		sn = sn.substring(1);
		for (int i = 0; i < _foreignLen; i++) {
			for (int j = 0; j < _sourceLen; j++) {
				if (_alignment[j][i] != 0) {
					reply += sn + " " + (j + 1) + " " + (i + 1) + " S \n";
				}
			}
		}
		return reply;
	}

	/**
	 * Outputs the alignment for GIZA format.
	 * Giza:
	 * Each alignment contains 3 sentences in output format
	 * The way each alignment is started is by having a sentence that starts
	 * with # followed by the sentence number, the source len, the targer len
	 * and the score.
	 * The second sentenc contains the foreign phrase.
	 * The thirds contains for each source word (null is word at position 0)
	 * the indexes of the word associated with it.
	 * 
	 * Example:
	 * # Sentence pair (13) source length 6 target length 6 alignment score : 3.97434e-09
	 * let us see the documents . 
	 * NULL ({ }) montrez ({ 1 3 }) - ({ }) nous ({ 2 }) les ({ 4 }) documents ({ 5 }) . ({ 6 }) 
	 * @param corpus
	 * @return
	 */
	public String toGizaFormat(BilingualCorpus corpus) {
		String reply = "";
		reply += "# Sentence pair (" + _sentenceNumber + ") source length "
		+ _sourceLen + " target length " + _foreignLen
		+ " alignment score : " + _score + "\n";
		for (int i = 0; i < _foreignLen - 1; i++) {
			reply += corpus.getForeignWord(_sentenceNumber, _sentenceSource, i)
			+ " ";
		}
		reply += corpus.getForeignWord(_sentenceNumber, _sentenceSource,
				_foreignLen - 1)
				+ "\n";
		String nullWords = "NULL {(";
		// Find null words
		for (int j = 0; j < _foreignLen; j++) {
			boolean nullA = true;
			for (int i = 0; i < _sourceLen; i++) {
				if (_alignment[i][j] != 0) {
					nullA = false;
					break;
				}
			}
			if (nullA) {
				nullWords += " " + (j + 1);
			}
		}
		nullWords += " )}";
		String aux = "";
		for (int i = 0; i < _sourceLen; i++) {
			aux += " "
				+ corpus.getSourceWord(_sentenceNumber, _sentenceSource, i)
				+ " ({";
			for (int j = 0; j < _foreignLen; j++) {

				if (_alignment[i][j] != 0) {
					aux += " " + (j + 1);
				}
			}
			aux += " })";
		}
		reply += nullWords + aux + "\n";
		return reply;
	}

	/**
	 * We need to receive the corpus where the alignments are coming from the sentence number and its source (training, dev, test).
	 * Having this info we only need the third line of the giza output format (see above).
	 * @param corpus
	 * @param sentenceNumber
	 * @param sentenceSource
	 * @param line1
	 * @param line2
	 * @param line3
	 * @return
	 */
	public static Alignment fromGizaFormat(BilingualCorpus corpus, int sentenceNumber, byte sentenceSource, String line1, String line2, String line3){
		int[] source = corpus.getSourceSentence(sentenceNumber, sentenceSource);
		int[] foreign = corpus.getForeignSentence(sentenceNumber, sentenceSource);
		Alignment al = new Alignment(sentenceNumber,sentenceSource,source.length,foreign.length);


		String[] split1 =Pattern.compile("\\}\\)").split(line3);
//		ignore the null
		for (int i = 1; i < split1.length; i++) {
			String inside = split1[i].trim();
			//System.out.println(inside);
			String[] insideSplit = inside.split("\\s+");
			//System.out.println(insideSplit.length);
			for (int foreignPosition = 2; foreignPosition < insideSplit.length; foreignPosition++) {
				//System.out.println("c " + insideSplit[foreignPosition]);
				//System.out.println("source pos " + (i-2) + " foreignPosition " + (Integer.parseInt(insideSplit[foreignPosition])-1));
				int sourcePos = i-1;
				int foreignPos = Integer.parseInt(insideSplit[foreignPosition])-1;
				try{
					al.add(sourcePos,foreignPos);
					al.addPosterior(sourcePos, foreignPos, 1);
				}catch(ArrayIndexOutOfBoundsException e){
					System.out.println(line1);
					System.out.println(line2);
					System.out.println(line3);
					System.out.println("Sentence number " + sentenceNumber + "sentenceSource " + sentenceSource);
					System.out.println(corpus.getSourceSentenceString(sentenceNumber, sentenceSource));
					System.out.println(corpus.getForeignSentenceString(sentenceNumber, sentenceSource));
					System.out.println("source len" + source.length);
					System.out.println("foreing len " + foreign.length);
					System.out.println("adding source " + sourcePos + " foreing " + foreignPos);
					throw e;
				}
			}
		}


		return al;
	}


	/**
	 * Prints and aligmnet for moses format
	 * Moses format consist in having one line for each alignment.
	 * Align points are represented as foreignPos-sourcePos
	 * It returns a String with the correponding alignment as 
	 * well as the source string and the foreing string.
	 * @param corpus
	 * @return
	 */
	public String[] toMosesFormat(BilingualCorpus corpus) {
		String[] result = new String[3];

		result[0] = toMosesFormat(corpus, 0, getSourceLenght(), 0, getForeignLenght());
		result[1] = corpus.getSourceSentenceString(_sentenceNumber,
				_sentenceSource);
		result[2] = corpus.getForeignSentenceString(_sentenceNumber,
				_sentenceSource);
		return result;
	}

	/**
	 * Prints and aligmnet for moses format
	 * Moses format consist in having one line for each alignment.
	 * Align points are represented as foreignPos-sourcePos
	 * It returns a String with the correponding alignment as 
	 * well as the source string and the foreing string.
	 * @param corpus
	 * @return
	 */
	public String toMosesFormat(BilingualCorpus corpus, int sourceStartPos, int sourceEndPos,int foreignStartPos, int foreignEndPos) {
		return toMosesFormat(corpus, sourceStartPos, sourceEndPos, foreignStartPos, foreignEndPos, 0,0);
	}
	
	/**
	 * Prints and aligmnet for moses format
	 * Moses format consist in having one line for each alignment.
	 * Align points are represented as foreignPos-sourcePos
	 * It returns a String with the correponding alignment as 
	 * well as the source string and the foreing string.
	 * @param corpus
	 * @return
	 */
	public String toMosesFormat(BilingualCorpus corpus, int sourceStartPos, int sourceEndPos,int foreignStartPos, int foreignEndPos, int relativeSource, int relativeForeign) {
		String al = "";
		for (int fpos = foreignStartPos; fpos <= foreignEndPos; fpos++) {
			for (int spos = sourceStartPos; spos <= sourceEndPos; spos++) {
				if (hasPosition(spos, fpos)) {
					al += (spos+relativeSource) + "-" + (fpos+relativeForeign) + " ";
				}
			}
		}
		return al;
	}

	//// SAVES ALIGNMENT TOGETHER WITH THEIR POSTERIORS
	//For each foreigh position saves one line with the posteriors for each source position concatenated
	//with a flag if the point was predicted or not ended by a new line

	public String[] toPosteriorFormat(BilingualCorpus corpus){
		String al = "s:" + _sentenceNumber + "\n";
		String[] result = new String[3];
		for (int foreignPos = 0; foreignPos < getForeignLenght(); foreignPos++) {
			for (int sourcePos = 0; sourcePos < getSourceLenght(); sourcePos++) {
				if (hasPosition(sourcePos, foreignPos)) {
					al += StaticTools.prettyPrint(this._posteriors[sourcePos][foreignPos], "0.0000E00", 8)+":"+"P";
				}else{
					al += StaticTools.prettyPrint(this._posteriors[sourcePos][foreignPos], "0.0000E00", 8)+":"+"N";
				}
				al+=" ";
			}
			al += "\n";
		}
		al += "\n";
		result[0] = al;
		result[1] = corpus.getSourceSentenceString(_sentenceNumber,
				_sentenceSource);
		result[2] = corpus.getForeignSentenceString(_sentenceNumber,
				_sentenceSource);
		return result;
	}



	public static void main(String[] args) throws IOException {

		System.out.println("Start main");
		String corpusDescription = args[0];
		int size = Integer.parseInt(args[1]); // 100k
		int maxSentenceSize = Integer.parseInt(args[2]); // 40


		String line1 = "# Sentence pair (1) source length 9 target length 9 alignment score : 9.31081e-16";
		String line2 = "do not force a moratorium down our throats . ";
		String line3 = "NULL ({ }) ne ({ 1 }) nous ({ }) forcez ({ 3 6 7 8 }) pas ({ 2 }) a ({ }) accepter ({ }) un ({ 4 }) moratoire ({ 5 }) . ({ 9 })";
		BilingualCorpus corpus = BilingualCorpus.getCorpusFromFileDescription(corpusDescription, size, maxSentenceSize).reverse();
		Alignment al = Alignment.fromGizaFormat(corpus, 0, BilingualCorpus.TEST_CORPUS, line1, line2, line3);
		AlignerOutput.output(al, corpus, System.out);
		/*
		 * 
		 * e1 e2 e3 e4 e5 ------------------- f1| X| | | | | f2| | X | | | | f3| |
		 * X | | | | f4| | | | | X | f5| | | | X | | ---------------------
		 * 
		 */
		/*
		ArrayList<Pair<Integer, Integer>> mask = new ArrayList<Pair<Integer, Integer>>();
		mask.add(new Pair<Integer, Integer>(-1, -1));
		mask.add(new Pair<Integer, Integer>(-1, 0));
		mask.add(new Pair<Integer, Integer>(0, -1));
		mask.add(new Pair<Integer, Integer>(0, 1));
		mask.add(new Pair<Integer, Integer>(1, 0));
		mask.add(new Pair<Integer, Integer>(1, 1));
		mask.add(new Pair<Integer, Integer>(-1, 1));
		mask.add(new Pair<Integer, Integer>(1, -1));

		Alignment a1 = new Alignment(0, (byte) 0, 5, 5);
		a1.add(0, 0);
		a1.add(1, 1);
		a1.add(1, 2);
		a1.add(4, 3);
		a1.add(3, 4);
		/*
		 * System.out.println(a1.toHazardFormat()); System.out.println("A1
		 * number of aligned points: " + a1.numberOfAlignedPoints());
		 * System.out.println("A1 number of lonely points: " +
		 * a1.numberOfLonelyPoints(mask)); System.out.println("A1 nmean
		 * fertility: " + a1.meanFertility()); System.out.println("A1 distance
		 * to diagonal: " + a1.distanceToDiagonal());
		 */
		//	System.out.println("Number of null 0: " + a1.getNumberNulls());

		/*
		 * 
		 * e1 e2 e3 e4 e5 ------------------- f1| X| | | | | f2| | X | | | | f3| | | | |
		 * X | f4| | | X | | | f5| X| | | | | ---------------------
		 * 
		 */
		/*
		Alignment a2 = new Alignment(0, (byte) 0, 5, 5);
		a2.add(0, 0);
		a2.add(1, 1);
		a2.add(4, 2);
		a2.add(2, 3);
		a2.add(0, 4);

		// System.out.println(a2.toHazardFormat());
		/*
		 * System.out.println("A2 number of aligned points: " +
		 * a2.numberOfAlignedPoints()); System.out.println("A2 number of lonely
		 * points: " + a2.numberOfLonelyPoints(mask)); System.out.println("A2
		 * nmean fertility: " + a2.meanFertility()); System.out.println("A2
		 * distance to diagonal: " + a2.distanceToDiagonal());
		 */
		//System.out.println("Number of null 0: " + a2.getNumberNulls());

		System.out.println("End main");

	}

	/*
	 * public String getSourceWord(int index){ return
	 * _source.getWord(_source.getSentence(_sentenceNumber)[index]); }
	 * 
	 * public String getForeignWord(int index){ return
	 * _foreign.getWord(_foreign.getSentence(_sentenceNumber)[index]); }
	 * 
	 * 
	 * public String[] getSourceWordIndexes(int foreignIndex){ int sourceLen =
	 * _source.getSentence(_sentenceNumber).length; String[] result = new
	 * String[sourceLen]; for(int i = 0;i<sourceLen;i++) result[i] =
	 * _alignment[i][foreignIndex]; return result; }
	 * 
	 * public boolean wordIndexesContainIndex(int foreignIndex, int
	 * indexToTest){ if (_alignment[indexToTest][foreignIndex] != null) return
	 * true; return false; }
	 */

	/*
	 * public String toString(){ String reply = ""; for(int i=0;i <
	 * fs.size();i++){ reply += i + "-" + fs.get(i) + " "; } reply += "\n";
	 * return reply; }
	 */

	
}
